﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.DirectoryServices;
using groupAnalyzer.model;
using groupAnalyzer.connectivity;
namespace groupAnalyzer.controller
{
    class NodeAnalyzer
    {
        private Factory factory;
        private LdapConnectivity connectivity;
        private Dictionary<string, DirectoryEntry> rawGroups;
        private string objectDn;
        private string analyzeMode;
    
        private Dictionary<string, Node> visited;

        private string getProperty(string objectDn, string propertyName)
        {
            string propertyValue = "";
            Object tmp = this.rawGroups[objectDn].Properties[propertyName];
            if (this.rawGroups[objectDn].Properties[propertyName].Value != null)
            {
                return this.rawGroups[objectDn].Properties[propertyName].ToString();
            }
            return propertyValue;
        }

        private string getProperty(string objectDn, string propertyName, int index)
        {
            string propertyValue = "";
            Object tmp = this.rawGroups[objectDn].Properties[propertyName];
            if (this.rawGroups[objectDn].Properties[propertyName].Value != null)
            {
                return this.rawGroups[objectDn].Properties[propertyName][index].ToString();
            }
            return propertyValue;
        }

        private void analyze(Node father, DirectoryEntry entry)
        {
            // get all children
            PropertyValueCollection membersRaw = entry.Properties[this.analyzeMode];
            // iterate over all children

            foreach (Object o in membersRaw)
            {
                string objectDn = o.ToString();
                if (!this.rawGroups.ContainsKey(objectDn))
                {
                    continue;
                }
                string name = this.getProperty(objectDn, "name", 0);
                string fqdn = objectDn;
                string description = this.getProperty(objectDn, "description", 0);
                string email = this.getProperty(objectDn, "mail", 0);
                string groupScope = "";
                string groupType = "";
                string notes = this.getProperty(objectDn, "info", 0);

                // construct node
                // check if node is already visited
                if (this.visited.ContainsKey(objectDn))
                {
                    Node child = this.visited[objectDn];
                    father.addChild(child, NodeConnectionMode.cyclic);
                }
                else
                {
                    Node child = this.factory.constructNode(name, fqdn, description, email, groupScope, groupType, notes);
                    father.addChild(child);
                    // put it into visited
                    this.visited[objectDn] = child;

                    // call analyze
                    this.analyze(child, this.rawGroups[o.ToString()]);
                }
            }
        }

        public void analyze()
        {

            this.rawGroups = connectivity.getAllGroupsHashmap();
            if (this.rawGroups.Count <= 0)
            {
                return;
            }
            string objectDn = this.objectDn;
            DirectoryEntry rootEntry = this.rawGroups[objectDn];
            // generate root entry
            string name = this.getProperty(objectDn, "name", 0);
            string fqdn = objectDn;
            string description = this.getProperty(objectDn, "description", 0);
            string email = this.getProperty(objectDn, "mail", 0);
            string groupScope = "";
            string groupType = "";
            string notes = this.getProperty(objectDn, "info", 0);

            Node root = this.factory.constructRootNode(name, fqdn, description, email, groupScope, groupType, notes);
            this.visited[objectDn] = root;
            this.analyze(root, rootEntry);
        }

        public NodeAnalyzer(Factory factory, LdapConnectivity connectivity, string objectDn, string analyzeMode)
        {
            this.objectDn = objectDn;
            this.analyzeMode = analyzeMode;
            this.factory = factory;
            this.visited = new Dictionary<string, Node>();
            this.connectivity = connectivity;
        }
    }
}
